using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace WindowsApplication1
{
    class Invariants
    {   // indeksy niezmiennikow w tablicy zwracanej przez 
        const byte m00 = 0;
        const byte n11 = 1;
        const byte n02 = 2;
        const byte n20 = 3;
        const byte n12 = 4;
        const byte n21 = 5;
        const byte n03 = 6;
        const byte n30 = 7;

        static double[] ni_pq(ref Bitmap bitm)
        { // liczenie wspolczynnika 'mi' oraz m, bedacych skladowa wsp. ni
            double[] tab_wsp = { 0, 0, 0, 0, 0, 0, 0, 0 };

            int scx = 0, scy = 0;   // srodki ciezkosci
            int powierzchnia = 0;

            // liczenie srodka ciezkosci obiektu
            for (int i = 0; i < bitm.Width; i++)
                for (int j = 0; j < bitm.Height; j++)
                {
                    string t1 = bitm.GetPixel(i, j).Name;
                    if (t1 == "ff000000" || t1 == "ff040404")
                    {
                        scx += i;
                        scy += j;
                        powierzchnia++;
                    }
                }

            // srodek ciezkosci - x, y
            scx = (int)scx / powierzchnia;
            scy = (int)scy / powierzchnia;

            // wyliczanie momentow centralnych i zwyklego - rzad p+q
            for ( int i = 0; i < bitm.Width; i++)
                for (int j = 0; j < bitm.Height; j++)
                {
                    string t2 = bitm.GetPixel(i, j).Name;
                    if (t2 == "ff000000" || t2 == "ff040404") // jesli czarny pix                    
                    {
                        // teoria - moment zwykly
                        // suma_em += Math.Pow(i, p) * Math.Pow(j, q);                        
                        tab_wsp[m00]++;  // praktyka p=0, q=0

                        //teoria - momenty centralne ('mi'[p, q])
                        // += Math.Pow(i - scx, p) * Math.Pow(j - scy, q);                        
                        tab_wsp[n11] += (i - scx) * (j - scy);
                        tab_wsp[n02] += Math.Pow(j - scy, 2);
                        tab_wsp[n20] += Math.Pow(i - scx, 2);
                        tab_wsp[n12] += (i - scx) * Math.Pow(j - scy, 2);
                        tab_wsp[n21] += Math.Pow(i - scx, 2) * (j - scy);
                        tab_wsp[n03] += Math.Pow(j - scy, 3);
                        tab_wsp[n30] += Math.Pow(i - scx, 3);                       
                    }
                }

            return tab_wsp;                                             
        }

        public static double[] Invariant123(Bitmap bmp)
        {
            double[] wyn_n = new double[8];
            double[] inv123 = new double[3];

            wyn_n = ni_pq(ref bmp);

            // I1
            inv123[0] = (wyn_n[n20] + wyn_n[n02]) / (wyn_n[m00] * wyn_n[m00]);

            // I2
            inv123[1] = (((wyn_n[n20] + wyn_n[n02]) * (wyn_n[n20] + wyn_n[n02]))
                      + 4 * wyn_n[n11] * wyn_n[n11]) / Math.Pow(wyn_n[m00], 4);

            // I3
            inv123[2] = ((wyn_n[n30] - 3 * wyn_n[n12]) * (wyn_n[n30] - 3 * wyn_n[n12]) +
                        (3 * wyn_n[n21] - wyn_n[n03]) * (3 * wyn_n[n21] - wyn_n[n03])) 
                        / Math.Pow(wyn_n[m00], 5);
          
            return inv123;
        }
    }
}
